package com.anti.modular.sys.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import com.anti.commom.constant.CommonConstant;
import com.anti.commom.context.constant.ConstantContextHolder;
import com.anti.commom.core.exception.BusinessException;
import com.anti.commom.core.exception.enums.PermissionExceptionEnum;
import com.anti.commom.enums.CommonStatusEnum;
import com.anti.core.context.login.LoginContextHolder;
import com.anti.jdbc.DBUtils;
import com.anti.jdbc.support.page.PageParam;
import com.anti.jdbc.support.page.PageResult;
import com.anti.modular.sys.emp.param.SysEmpParam;
import com.anti.modular.sys.emp.result.SysEmpInfo;
import com.anti.modular.sys.emp.service.SysEmpService;
import com.anti.modular.sys.user.dao.SysUserDao;
import com.anti.modular.sys.user.enums.SysUserAdminTypeEnum;
import com.anti.modular.sys.user.factory.SysUserFactory;
import com.anti.modular.sys.user.param.SysUserParam;
import com.anti.modular.sys.user.entity.SysUser;
import com.anti.modular.sys.user.pojo.result.SysUserResult;
import com.anti.modular.sys.user.service.SysUserDataScopeService;
import com.anti.modular.sys.user.service.SysUserRoleService;
import com.anti.modular.sys.user.service.SysUserService;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @Description TODO
 * @Author anTi
 * @Date 2021-2-24
 */
@Service
public class SysUserServiceImpl implements SysUserService {
    @Resource
    DBUtils dbUtils;
    @Resource
    SysUserDao sysUserDao;
    @Resource
    SysEmpService sysEmpService;
    @Resource
    SysUserRoleService sysUserRoleService;
    @Resource
    SysUserDataScopeService sysUserDataScopeService;

    @Override
    public PageResult page(PageParam pageParam, SysUserParam sysUserParam) {
        StringBuilder sb=new StringBuilder("select * from sys_user  where 1=1 ");
        HashMap<Object, Object> params = CollectionUtil.newHashMap();
        if (ObjectUtil.isNotNull(sysUserParam)) {
            //根据关键字模糊查询（姓名，账号，手机号）
            if (ObjectUtil.isNotEmpty(sysUserParam.getSearchValue())) {
                sb.append(" and (account like:account or name like :name or phone like :phone ) ");
                params.put("account","%"+sysUserParam.getSearchValue()+"%");
                params.put("name","%"+sysUserParam.getSearchValue()+"%");
                params.put("phone","%"+sysUserParam.getSearchValue()+"%");
            }
            //根据员工所属机构查询
            if (ObjectUtil.isNotEmpty(sysUserParam.getSysEmpParam())) {
                SysEmpParam sysEmpParam = sysUserParam.getSysEmpParam();
                if (ObjectUtil.isNotEmpty(sysEmpParam.getOrgId())) {
                    //查询属于该机构的，或该机构下级所有的人员
                    sb.append(" and id in (select  id from sys_emp where org_id=:orgId or org_id in (select id from sys_org WHERE pids like :pids )) ");
                    params.put("orgId",sysEmpParam.getOrgId());
                    params.put("pids","%"+sysEmpParam.getOrgId()+"%");
                }
            }
            //根据状态查询（0正常 1停用），删除的不会展示在列表
            if (ObjectUtil.isNotEmpty(sysUserParam.getSearchStatus())) {
                sb.append(" and status=:status ");
                params.put("status",sysUserParam.getSearchStatus());
            }
        }
        //如果是超级管理员则获取所有用户，否则只获取其数据范围的用户
        boolean superAdmin = LoginContextHolder.me().isSuperAdmin();
        if (!superAdmin) {
            List<Long> dataScope = sysUserParam.getDataScope();
            if (ObjectUtil.isEmpty(dataScope)) {
                return new PageResult();
            } else {
                Set<Long> dataScopeSet = CollectionUtil.newHashSet(dataScope);
                sb.append(" and id in (select id from sys_emp where org_id in (:orgIds)) ");
                params.put("orgIds",dataScopeSet);
            }
        }
        PageResult result = dbUtils.query(pageParam, sb.toString(), SysUserResult.class,params);
        return result;
    }

    @Override
    public void add(SysUserParam sysUserParam) {
        checkParam(sysUserParam, false);
        boolean superAdmin = LoginContextHolder.me().isSuperAdmin();
        //如果登录用户不是超级管理员，则进行数据权限校验
        if (!superAdmin) {
            List<Long> dataScope = sysUserParam.getDataScope();
            //获取添加的用户的所属机构
            Long orgId = sysUserParam.getSysEmpParam().getOrgId();
            //数据范围为空
            if (ObjectUtil.isEmpty(dataScope)) {
                throw new BusinessException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
            } else if (!dataScope.contains(orgId)) {
                //所添加的用户的所属机构不在自己的数据范围内
                throw new BusinessException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
            }
        }
        SysUser sysUser = new SysUser();
        BeanUtil.copyProperties(sysUserParam, sysUser);
        SysUserFactory.fillAddCommonUserInfo(sysUser);
        sysUser.setPassword(BCrypt.hashpw(sysUser.getPassword(), BCrypt.gensalt()));
        sysUser.setCreateTime(new Date());
        sysUser.setCreateUser(LoginContextHolder.me().getSysLoginUserId());

        sysUserDao.save(sysUser);
        Long sysUserId = sysUser.getId();
        //增加员工信息
        SysEmpParam sysEmpParam = sysUserParam.getSysEmpParam();
        sysEmpParam.setId(sysUserId);
        sysEmpService.addOrUpdate(sysEmpParam);
    }

    @Override
    public void delete(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        //不能删除超级管理员
        if (SysUserAdminTypeEnum.SUPER_ADMIN.getCode().equals(sysUser.getAdminType())) {
            throw new BusinessException(0,"不能删除超级管理员");
        }
        boolean superAdmin = LoginContextHolder.me().isSuperAdmin();
        //如果登录用户不是超级管理员，则进行数据权限校验
        if (!superAdmin) {
            List<Long> dataScope = sysUserParam.getDataScope();
            //获取要删除的用户的所属机构
            SysEmpInfo sysEmpInfo = sysEmpService.getSysEmpInfo(sysUser.getId());
            Long orgId = sysEmpInfo.getOrgId();
            //数据范围为空
            if (ObjectUtil.isEmpty(dataScope)) {
                throw new BusinessException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
            } else if (!dataScope.contains(orgId)) {
                //所要删除的用户的所属机构不在自己的数据范围内
                throw new BusinessException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
            }
        }
        sysUser.setStatus(CommonStatusEnum.DELETED.getCode());
        sysUserDao.update(sysUser);
        Long id = sysUser.getId();
        //删除该用户对应的员工表信息
        sysEmpService.deleteEmpInfoByUserId(id);

        //删除该用户对应的用户-角色表关联信息
        sysUserRoleService.deleteUserRoleListByUserId(id);

        //删除该用户对应的用户-数据范围表关联信息
        sysUserDataScopeService.deleteUserDataScopeListByUserId(id);
    }

    @Override
    public void edit(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        checkParam(sysUserParam, true);
        boolean superAdmin = LoginContextHolder.me().isSuperAdmin();
        //如果登录用户不是超级管理员，则进行数据权限校验
        if (!superAdmin) {
            List<Long> dataScope = sysUserParam.getDataScope();
            //获取要编辑的用户的所属机构
            Long orgId = sysUserParam.getSysEmpParam().getOrgId();
            //数据范围为空
            if (ObjectUtil.isEmpty(dataScope)) {
                throw new BusinessException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
            } else if (!dataScope.contains(orgId)) {
                //所要编辑的用户的所属机构不在自己的数据范围内
                throw new BusinessException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
            }
        }

        BeanUtil.copyProperties(sysUserParam, sysUser);
        //不能修改状态，用修改状态接口修改状态
        sysUser.setStatus(null);
        //设置密码
        SysUserFactory.fillBaseUserInfo(sysUser);
        sysUserDao.update(sysUser);
        Long sysUserId = sysUser.getId();
        //编辑员工信息
        SysEmpParam sysEmpParam = sysUserParam.getSysEmpParam();
        BeanUtil.copyProperties(sysUserParam, sysEmpParam);
        sysEmpParam.setId(sysUserId);
        sysEmpService.addOrUpdate(sysEmpParam);
    }

    @Override
    public SysUserResult detail(SysUserParam sysUserParam) {
        SysUserResult sysUserResult = new SysUserResult();
        //获取系统用户
        SysUser sysUser = this.querySysUser(sysUserParam);
        BeanUtil.copyProperties(sysUser, sysUserResult);
        //获取对应员工信息
        SysEmpInfo sysEmpInfo = sysEmpService.getSysEmpInfo(sysUser.getId());
        //设置员工信息
        sysUserResult.setSysEmpInfo(sysEmpInfo);
        return sysUserResult;
    }

    @Override
    public void saveChangeStatus(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        //不能修改超级管理员状态
        if (SysUserAdminTypeEnum.SUPER_ADMIN.getCode().equals(sysUser.getAdminType())) {
            throw new BusinessException(0,"不能修改超级管理员状态");
        }

        Long id = sysUser.getId();

        Integer status = sysUserParam.getStatus();
        //校验状态在不在枚举值里
        CommonStatusEnum.validateStatus(status);

        //更新枚举，更新只能更新未删除状态的
        boolean update = sysUserDao.updateStatus(status,id);
        if (!update) {
            throw new BusinessException(0,"更新状态失败，您试图更新被删除的记录");
        }
    }

    @Override
    public void saveGrantRole(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        boolean superAdmin = LoginContextHolder.me().isSuperAdmin();
        //如果登录用户不是超级管理员，则进行数据权限校验
        if (!superAdmin) {
            List<Long> dataScope = sysUserParam.getDataScope();
            //获取要授权角色的用户的所属机构
            SysEmpInfo sysEmpInfo = sysEmpService.getSysEmpInfo(sysUser.getId());
            Long orgId = sysEmpInfo.getOrgId();
            //数据范围为空
            if (ObjectUtil.isEmpty(dataScope)) {
                throw new BusinessException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
            } else if (!dataScope.contains(orgId)) {
                //所要授权角色的用户的所属机构不在自己的数据范围内
                throw new BusinessException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
            }
        }
        sysUserRoleService.saveGrantRole(sysUserParam);
    }

    @Override
    public void saveGrantData(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        boolean superAdmin = LoginContextHolder.me().isSuperAdmin();
        //如果登录用户不是超级管理员，则进行数据权限校验
        if (!superAdmin) {
            List<Long> dataScope = sysUserParam.getDataScope();
            //获取要授权数据的用户的所属机构
            SysEmpInfo sysEmpInfo = sysEmpService.getSysEmpInfo(sysUser.getId());
            Long orgId = sysEmpInfo.getOrgId();
            //数据范围为空
            if (ObjectUtil.isEmpty(dataScope)) {
                throw new BusinessException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
            } else if (!dataScope.contains(orgId)) {
                //所要授权数据的用户的所属机构不在自己的数据范围内
                throw new BusinessException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
            }
        }
        sysUserDataScopeService.saveGrantData(sysUserParam);
    }

    @Override
    public void updateInfo(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        BeanUtil.copyProperties(sysUserParam, sysUser);
        sysUserDao.update(sysUser);
    }

    @Override
    public void updatePwd(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        //新密码与原密码相同
        if (sysUserParam.getNewPassword().equals(sysUserParam.getPassword())) {
            throw new BusinessException(0,"新密码与原密码相同，请检查newPassword参数");
        }
        //原密码错误
        if (!BCrypt.checkpw(sysUserParam.getPassword(), sysUser.getPassword())) {
            throw new BusinessException(0,"原密码错误，请检查password参数");
        }
        sysUser.setPassword(BCrypt.hashpw(sysUserParam.getNewPassword(), BCrypt.gensalt()));
        sysUserDao.update(sysUser);
    }


    @Override
    public List<Long> ownRole(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        return sysUserRoleService.getUserRoleIdList(sysUser.getId());
    }

    @Override
    public List<Long> ownData(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        return sysUserDataScopeService.getUserDataScopeIdList(sysUser.getId());
    }

    @Override
    public void saveResetPwd(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        String password = ConstantContextHolder.getDefaultPassWord();
        sysUser.setPassword(BCrypt.hashpw(password, BCrypt.gensalt()));
        sysUserDao.update(sysUser);
    }

    @Override
    public void updateAvatar(SysUserParam sysUserParam) {
        SysUser sysUser = this.querySysUser(sysUserParam);
        Long avatar = sysUserParam.getAvatar();
        //判断文件是否存在
        //sysFileInfoService.assertFile(avatar);
        sysUser.setAvatar(avatar);
        sysUserDao.update(sysUser);
    }

    @Override
    public List<Dict> selector(SysUserParam sysUserParam) {
        List<Dict> dictList = CollectionUtil.newArrayList();
        //查询非删除状态，排除超级管理员
        StringBuilder sb=new StringBuilder("SELECT * FROM sys_user WHERE STATUS=0 and admin_type <> 1 ");
        ArrayList<Object> params = CollectionUtil.newArrayList();
        if (ObjectUtil.isNotNull(sysUserParam)) {
            //根据姓名模糊查询
            if (ObjectUtil.isNotEmpty(sysUserParam.getName())) {
                sb.append(" and name like ? ");
                params.add("%"+sysUserParam.getName()+"%");
            }
        }
        List<SysUser> sysUserList = dbUtils.query(sb.toString(), SysUser.class, params.toArray());
        sysUserList.forEach(sysUser -> {
            Dict dict  = Dict.create();
            dict.put(CommonConstant.ID, sysUser.getId());
            dict.put(CommonConstant.NAME, sysUser.getName());
            dictList.add(dict);
        });
        return dictList;
    }

    @Override
    public SysUser getUserByCount(String account) {
        SysUser user = dbUtils.getFirst("SELECT * FROM sys_user WHERE account=?", SysUser.class, account);
        return user;
    }

    @Override
    public SysUser getById(Long userId) {
        SysUser user = dbUtils.getFirst("SELECT * FROM sys_user WHERE id=?", SysUser.class, userId);
        return user;
    }

    @Override
    public List<Long> getUserDataScopeIdList(Long userId, Long orgId) {
        Set<Long> userDataScopeIdSet = CollectionUtil.newHashSet();
        if (ObjectUtil.isAllNotEmpty(userId, orgId)) {

            //获取该用户对应的数据范围集合
            List<Long> userDataScopeIdListForUser = sysUserDataScopeService.getUserDataScopeIdList(userId);

            //获取该用户的角色对应的数据范围集合
            List<Long> userDataScopeIdListForRole = sysUserRoleService.getUserRoleDataScopeIdList(userId, orgId);

            userDataScopeIdSet.addAll(userDataScopeIdListForUser);
            userDataScopeIdSet.addAll(userDataScopeIdListForRole);
        }
        return CollectionUtil.newArrayList(userDataScopeIdSet);
    }

    @Override
    public String getNameByUserId(Long userId) {
        SysUser sysUser = this.getById(userId);
        if (ObjectUtil.isNull(sysUser)) {
            throw new BusinessException(0,"用户不存在");
        }
        return sysUser.getName();
    }

    /**
     * 校验参数，检查是否存在相同的账号
     */
    private void checkParam(SysUserParam sysUserParam, boolean b) {
        Long id = sysUserParam.getId();
        String account = sysUserParam.getAccount();
        ArrayList<Object> params = CollectionUtil.newArrayList();
        StringBuilder sb=new StringBuilder("select count(*) from sys_user where status=0 and account=? ");
        params.add(account);
        //是否排除自己，如果是则查询条件排除自己id
        if (b){
            sb.append(" and id <> ? ");
            params.add(id);
        }
        int countByAccount = dbUtils.getFirst(sb.toString(),Integer.class,params.toArray());
        //大于等于1个则表示重复
        if (countByAccount >= 1) {
            throw new BusinessException(0,"账号已存在，请检查account参数");
        }
    }

    /**
     * 获取系统用户
     */
    private SysUser querySysUser(SysUserParam sysUserParam) {
        SysUser sysUser = this.getById(sysUserParam.getId());
        if (ObjectUtil.isNull(sysUser)) {
            throw new BusinessException(0,"用户不存在");
        }
        return sysUser;
    }

}
